home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / mush6.4 / part12 < prev    next >
Encoding:
Internet Message Format  |  1989-03-12  |  29.4 KB

  1. Subject:  v18i034:  Mail user's shell version 6.4, Part12/19
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Dan Heller <island!argv@sun.com>
  7. Posting-number: Volume 18, Issue 34
  8. Archive-name: mush6.4/part12
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 12 (of 19)."
  19. # Contents:  curses.c
  20. # Wrapped by rsalz@papaya.bbn.com on Mon Mar 13 19:25:18 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'curses.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'curses.c'\"
  24. else
  25. echo shar: Extracting \"'curses.c'\" \(27579 characters\)
  26. sed "s/^X//" >'curses.c' <<'END_OF_FILE'
  27. X/* @(#)curses.c    (c) copyright 3/18/87 (Dan Heller) */
  28. X
  29. X/* curses.c -- routine to deal with the curses interface */
  30. X#ifdef CURSES
  31. X
  32. X#include "mush.h"
  33. X#include "bindings.h"
  34. X
  35. Xcurses_init(argc, argv)
  36. Xregister char **argv;
  37. X{
  38. X    char buf[80];
  39. X    extern char *UP, ttytype[];
  40. X
  41. X    if (argv && *++argv && !strcmp(*argv, "-?"))
  42. X    return help(0, "curses", cmd_help);
  43. X    if (iscurses) {
  44. X    print("You can't run curses from the curses mode (silly).");
  45. X    return -1;
  46. X    }
  47. X    if (ison(glob_flags, IS_GETTING)) {
  48. X    print("Finish your letter first.\n");
  49. X    return -1;
  50. X    }
  51. X#ifdef SUNTOOL
  52. X    if (istool) {
  53. X    print("My, aren't we the adventuresome type!");
  54. X    timerclear(&(mail_timer.it_interval));
  55. X    timerclear(&(mail_timer.it_value));
  56. X    istool = FALSE, tool_destroy(tool);
  57. X    curses_init(0, 0);
  58. X    do_loop(); /* doesn't return */
  59. X    }
  60. X#endif /* SUNTOOL */
  61. X
  62. X#ifndef attrset        /* terminfo version of curses */
  63. X    /* you can not start curses in no echo mode.. must be in normal mode */
  64. X    echom();
  65. X    nocrmode();
  66. X#endif /* attrset */
  67. X    (void) initscr();
  68. X#ifdef SIGCONT
  69. X    /* initscr will play with signals -- make sure they're set right. */
  70. X    (void) signal(SIGTSTP, stop_start);
  71. X    (void) signal(SIGCONT, stop_start);
  72. X#endif /* SIGCONT */
  73. X#if !defined(SYSV) && !defined(USG)
  74. X    if (!UP || !*UP)
  75. X#else /* ~SYSV && ~USG */
  76. X    if (!stdscr)
  77. X#endif /* ~SYSV && ~USG */
  78. X         {
  79. X    print("Terminal type %s can not use the curses interface.\n", ttytype);
  80. X    return -1;
  81. X    }
  82. X    iscurses = TRUE;
  83. X    noechom(); /* reset tty state -- */
  84. X    crmode(); /* do not use "echo_on/off()" */
  85. X    scrollok(stdscr, TRUE);
  86. X    /* if the user hasn't set his screen explicitly, set it for him */
  87. X    set_screen_size();
  88. X    crt = LINES;
  89. X    (void) cmd_line(sprintf(buf, "\\set screen = %d crt = %d", screen, crt),
  90. X    msg_list);
  91. X    if (argc) {
  92. X    (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1), msg_list);
  93. X    (void) curses_help_msg(TRUE);
  94. X    }
  95. X    if (!do_set(set_options, "no_reverse"))
  96. X    turnon(glob_flags, REV_VIDEO);
  97. X    turnoff(glob_flags, CONT_PRNT);
  98. X    return 0; /* doesn't affect messages */
  99. X}
  100. X
  101. Xstruct cmd_map *active_cmd;    /* See bindings.h for description */
  102. X
  103. X/*
  104. X * get input in cbreak mode and execute the appropriate command.
  105. X * when the command is done (usually), the user is prompted to
  106. X * hit any key to continue. At this point, the user may enter a
  107. X * new command so no screen refreshing needs to be done. This
  108. X * new command is returned to caller and may be passed back.
  109. X *
  110. X * The flag CNTD_CMD (continued command) is set if
  111. X * this routine is called with the passed parameter (c) != 0. If
  112. X * so, then the character passed is the character input by the
  113. X * user at the last "hit return" prompt indicating that he wants
  114. X * to execute a new command and not draw the screen.
  115. X *
  116. X * CNTD_CMD is also set if the command that the user invokes
  117. X * causes any sort of output that requires a screen refresh.  The
  118. X * variable redo is set to 1 if the header page not only requires
  119. X * redrawing, but updating ... (new call to do_hdrs)
  120. X *
  121. X * calls that say: print("%s", compose_hdr(current_msg)) are constructed
  122. X * that way because if the header has a `%' in it, then print will try to
  123. X * expand it.
  124. X */
  125. Xcurses_command(c)
  126. Xregister int c;
  127. X{
  128. X    char    buf[BUFSIZ], file[128], list[128];
  129. X    int     n, curlin;
  130. X    static int  redo = 0;  /* set if headers should be redrawn */
  131. X
  132. X    if (c != 0)
  133. X    turnon(glob_flags, CNTD_CMD);
  134. X    else
  135. X    turnoff(glob_flags, CNTD_CMD);
  136. X    clear_msg_list(msg_list); /* play it safe */
  137. X    if (isoff(glob_flags, CNTD_CMD)) {
  138. X    (void) check_new_mail();
  139. X    curlin = max(1, current_msg - n_array[0] + 1);
  140. X    scrn_line(curlin, buf);
  141. X    if (ison(glob_flags, REV_VIDEO) && msg_cnt)
  142. X        STANDOUT(curlin, 0, buf);
  143. X    mail_status(0);
  144. X    move(curlin, 0), refresh();
  145. X    /* reprint to remove reverse video from current line (don't refresh) */
  146. X    if (ison(glob_flags, REV_VIDEO))
  147. X        mvaddstr(curlin, 0, buf);
  148. X    c = getcmd(); /* get input AFTER line redrawn without reverse video */
  149. X    }
  150. X    buf[0] = list[0] = file[0] = '\0';
  151. X
  152. X    if (c == C_WRITE_LIST || c == C_SAVE_LIST || c == C_COPY_LIST
  153. X       || c == C_DELETE_LIST || c == C_UNDEL_LIST) {
  154. X    if (msg_cnt < 1) {
  155. X        mac_flush();
  156. X        print("Not enough messages.");
  157. X        c = C_NULL;
  158. X    } else if (c == C_DELETE_LIST && ison(glob_flags, READ_ONLY)) {
  159. X        mac_flush();
  160. X        print("Folder is read-only.");
  161. X        c = C_NULL;
  162. X    } else if (!curses_msg_list(sprintf(buf, "%s msg list: ",
  163. X        (c == C_WRITE_LIST)? "write" : (c == C_SAVE_LIST)?  "save" :
  164. X        (c == C_COPY_LIST)? "copy" :
  165. X        (c == C_DELETE_LIST)? "delete" : "undelete"), list, msg_list))
  166. X        c = C_NULL;
  167. X    if (ison(glob_flags, CNTD_CMD))
  168. X        putchar('\n');
  169. X    }
  170. X
  171. X    /* first do non-mail command type stuff */
  172. X    switch (c) {
  173. X    case C_ERROR :
  174. X        bell();
  175. X        mac_flush();
  176. X
  177. X    when C_NULL :
  178. X        if (isoff(glob_flags, CNTD_CMD))
  179. X        bell();
  180. X
  181. X    /* goto a specific message number */
  182. X    when C_GOTO_MSG :
  183. X        if (msg_cnt <= 1) {
  184. X        print("Not enough messages.");
  185. X        mac_flush(); /* Flush any digit or other macros */
  186. X        } else
  187. X        if (curses_msg_list(strcpy(buf, "goto msg: "), list, msg_list)) {
  188. X        /*
  189. X         * Reset the current message in case a 
  190. X         * backquoted command (like `from`) changed it
  191. X         */
  192. X        n = current_msg;
  193. X        do if (++n >= msg_cnt)
  194. X            n = 0;
  195. X        while (n != current_msg && !msg_bit(msg_list, n));
  196. X        if (n == current_msg && !msg_bit(msg_list, n)) {
  197. X            mac_flush(); /* bail out if in macro processing */
  198. X            print("Message not found.");
  199. X        }
  200. X        else if ((current_msg = n) < n_array[0]
  201. X            || n > n_array[screen-1])
  202. X            redo = 1;
  203. X        } else {
  204. X        mac_flush();
  205. X        bell();
  206. X        }
  207. X        if (ison(glob_flags, CNTD_CMD) && msg_cnt)
  208. X        print("%-.*s", COLS-2, compose_hdr(current_msg));
  209. X        if (ison(glob_flags, CNTD_CMD))
  210. X        putchar('\n');
  211. X
  212. X    /* screen optimization stuff */
  213. X    when C_REVERSE :
  214. X        if (ison(glob_flags, REV_VIDEO))
  215. X        turnoff(glob_flags, REV_VIDEO);
  216. X        else
  217. X        turnon(glob_flags, REV_VIDEO);
  218. X
  219. X    when C_REDRAW : redo = 1;
  220. X
  221. X    /*
  222. X     * screen movement
  223. X     */
  224. X    when C_NEXT_MSG :
  225. X        if (current_msg + 2 > msg_cnt ||
  226. X        isoff(glob_flags, CNTD_CMD) && curlin == LINES-2) {
  227. X        mac_flush();    /* Bail out if in macro processing */
  228. X        bell();        /* reached the end */
  229. X        } else {
  230. X        if (ison(glob_flags, CNTD_CMD)) {
  231. X            if (++current_msg > n_array[screen-1])
  232. X            redo = 1;
  233. X            print("%-.*s", COLS-2, compose_hdr(current_msg));
  234. X            putchar('\n');
  235. X        } else {
  236. X            if (++current_msg > n_array[screen-1])
  237. X            n_array[screen++] = current_msg;
  238. X            move(++curlin, 0);
  239. X            printw("%-.*s", COLS-2, compose_hdr(current_msg));
  240. X            clrtoeol();
  241. X        }
  242. X        }
  243. X
  244. X    when C_PREV_MSG :
  245. X        if (isoff(glob_flags, CNTD_CMD) && curlin == 1 || current_msg == 0)
  246. X        {
  247. X        mac_flush();    /* Bail out if in macro processing */
  248. X        bell();      /* at the beginning */
  249. X        } else {
  250. X        if (--current_msg < n_array[0])
  251. X            redo = 1;
  252. X        if (ison(glob_flags, CNTD_CMD)) {
  253. X            print("%-.*s", COLS-2, compose_hdr(current_msg));
  254. X            putchar('\n');
  255. X        }
  256. X        }
  257. X
  258. X    when C_FIRST_MSG : case C_LAST_MSG :
  259. X        n = current_msg;
  260. X        move(LINES-1, 0), refresh();
  261. X        if (c == C_FIRST_MSG && (current_msg = 0) < n_array[0] ||
  262. X        c == C_LAST_MSG && (current_msg = msg_cnt-1)> n_array[screen-1])
  263. X        if (isoff(glob_flags, CNTD_CMD))
  264. X            (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1),
  265. X                 msg_list);
  266. X        else
  267. X            redo = 1;
  268. X        if (ison(glob_flags, CNTD_CMD) && n != current_msg)
  269. X        print("%-.*s", COLS-2, compose_hdr(current_msg)), putchar('\n');
  270. X
  271. X    /* top and bottom of headers screen */
  272. X    when C_TOP_PAGE : case C_BOTTOM_PAGE :
  273. X        if (isoff(glob_flags, CNTD_CMD))
  274. X        if (c == C_TOP_PAGE)
  275. X            current_msg = n_array[0];
  276. X        else
  277. X            current_msg = min(n_array[screen-1], msg_cnt-1);
  278. X        else {
  279. X        mac_flush();
  280. X        bell();
  281. X        }
  282. X
  283. X    when C_NEXT_SCREEN : /* next page */
  284. X        move(LINES-1, 0), refresh();
  285. X        if (msg_cnt-1 > n_array[screen-1]) {
  286. X        clear();
  287. X        set_screen_size();
  288. X        (void) cmd_line(strcpy(buf, "\\headers +"), msg_list);
  289. X        if (current_msg < n_array[0])
  290. X            current_msg = n_array[0];
  291. X        (void) curses_help_msg(TRUE);
  292. X        return redo = 0;
  293. X        } else {
  294. X        mac_flush();
  295. X        bell();
  296. X        }
  297. X
  298. X    when C_PREV_SCREEN : /* previous page */
  299. X        move(LINES-1, 0), refresh();
  300. X        if (n_array[0] > 0) {
  301. X        clear();
  302. X        set_screen_size();
  303. X        (void) cmd_line(strcpy(buf, "\\headers -"), msg_list);
  304. X        if (current_msg > n_array[screen-1])
  305. X            current_msg = n_array[screen-1];
  306. X        (void) curses_help_msg(TRUE);
  307. X        return redo = 0;
  308. X        } else {
  309. X        mac_flush();
  310. X        bell();
  311. X        }
  312. X
  313. X    /* read from/save to record file (.mushrc) */
  314. X    when C_SOURCE : case C_SAVEOPTS : {
  315. X        int argc;
  316. X        char *argv[3];
  317. X        print("%s filename [default]: ",
  318. X        (c == C_SOURCE)? "source" : "save options to");
  319. X        argc = Getstr(file, LINES-40, 0);
  320. X        clr_bot_line();
  321. X        if (argc < 0)
  322. X        return 0;
  323. X        if (argc > 0)
  324. X        argv[1] = file, argc = 2;
  325. X        else
  326. X        argc = 1;
  327. X        argv[argc] = NULL;
  328. X        turnon(glob_flags, PRE_CURSES);
  329. X        if (c == C_SOURCE)
  330. X        (void) source(argc, argv);
  331. X        else
  332. X        (void) save_opts(argc, argv);
  333. X        turnoff(glob_flags, PRE_CURSES);
  334. X    }
  335. X
  336. X    /*
  337. X     * search commands
  338. X     */
  339. X    when C_NEXT_SEARCH : case C_PREV_SEARCH : case C_CONT_SEARCH :
  340. X        if (c != C_CONT_SEARCH)
  341. X        c = search(0 + (c == C_PREV_SEARCH));
  342. X        else
  343. X        c = search(-1);
  344. X        if (ison(glob_flags, CNTD_CMD))
  345. X        putchar('\n');
  346. X        if (c == 0)
  347. X        break;
  348. X        if (ison(glob_flags, CNTD_CMD))
  349. X        print("%-.*s",COLS-2, compose_hdr(current_msg)), putchar('\n');
  350. X        if (n_array[0] > current_msg || n_array[screen-1] < current_msg) {
  351. X        redo = 1;
  352. X        if (isoff(glob_flags, CNTD_CMD))
  353. X            (void) cmd_line(sprintf(buf, "\\headers %d",
  354. X                        current_msg+1), msg_list);
  355. X        }
  356. X
  357. X    /*
  358. X     * actions on messages
  359. X     */
  360. X    /* delete/undelete */
  361. X    when C_DELETE_MSG : case C_DELETE_LIST :
  362. X    case C_UNDEL_MSG : case C_UNDEL_LIST :
  363. X        if (!msg_cnt) {
  364. X        print("No messages.");
  365. X        if (ison(glob_flags, CNTD_CMD))
  366. X            putchar('\n');
  367. X        break;
  368. X        }
  369. X        if (ison(glob_flags, READ_ONLY)) {
  370. X        mac_flush();
  371. X        print("Folder is read-only.");
  372. X        if (ison(glob_flags, CNTD_CMD))
  373. X            putchar('\n');
  374. X        break;
  375. X        }
  376. X        Debug("current message = %d", current_msg + 1);
  377. X        if (!*list)
  378. X        set_msg_bit(msg_list, current_msg);
  379. X        turnon(glob_flags, DO_UPDATE);
  380. X        for (n = 0; n < msg_cnt; n++)
  381. X        if (msg_bit(msg_list, n)) {
  382. X            if (c == C_DELETE_MSG || c == C_DELETE_LIST)
  383. X            turnon(msg[n].m_flags, DELETE);
  384. X            else
  385. X            turnoff(msg[n].m_flags, DELETE);
  386. X            if (isoff(glob_flags, CNTD_CMD) && (msg_cnt < screen ||
  387. X            n >= n_array[0] && n <= n_array[screen-1])) {
  388. X            move(max(1, n - n_array[0] + 1), 0);
  389. X            printw("%-.*s", COLS-1, compose_hdr(n));
  390. X            } else
  391. X            redo = 1;
  392. X        }
  393. X        if (ison(glob_flags, CNTD_CMD) || *list) {
  394. X        /* print(), THEN putchar() -- overwrite line */
  395. X        if (ison(glob_flags, CNTD_CMD)) {
  396. X            print("%sdeleted %s",
  397. X            (c == C_DELETE_MSG || c == C_DELETE_LIST)? "":"un", list);
  398. X            putchar('\n');
  399. X        }
  400. X        if (ison(msg[current_msg].m_flags, DELETE) ||
  401. X            ison(msg[current_msg].m_flags, SAVED))
  402. X            (void) next_msg();
  403. X        if (isoff(msg[current_msg].m_flags, DELETE) &&
  404. X            do_set(set_options, "autoprint"))
  405. X            return C_DISPLAY_MSG;
  406. X        if (ison(glob_flags, CNTD_CMD))
  407. X            puts(compose_hdr(current_msg));
  408. X        else if (current_msg < n_array[0]
  409. X            || current_msg > n_array[screen-1])
  410. X            redo = 1;
  411. X        }
  412. X
  413. X    /*
  414. X     * write/save messages.  If a list is necessary, the user already
  415. X     * entered it above since he must have used a capital letter. If so,
  416. X     * list will contain good data (already been validated above).
  417. X     * if a list is given, set iscurses to 0 so that print statements
  418. X     * will scroll and the user sees the multiple output. else, one
  419. X     * line can go on the bottom line just fine.
  420. X     */
  421. X    when C_WRITE_MSG : case C_SAVE_MSG : case C_COPY_MSG :
  422. X    case C_WRITE_LIST : case C_SAVE_LIST : case C_COPY_LIST : {
  423. X        register char *p =
  424. X        (c == C_WRITE_MSG || c == C_WRITE_LIST)? "write" :
  425. X        (c == C_SAVE_MSG  || c == C_SAVE_LIST)? "save" : "copy";
  426. X        if (!msg_cnt) {
  427. X        print("No messages.");
  428. X        if (ison(glob_flags, CNTD_CMD))
  429. X            putchar('\n');
  430. X        break;
  431. X        }
  432. X        print(sprintf(buf, "filename to %s%s: ", p,
  433. X        (c != C_WRITE_MSG && c != C_WRITE_LIST)? " [mbox]" : ""));
  434. X        if (Getstr(file, COLS-1-strlen(buf), 0) >= 0) {
  435. X        char *argv[3];
  436. X        clr_bot_line();
  437. X        argv[0] = strcpy(buf, p);
  438. X        argv[1] = (*file) ? file : NULL;
  439. X        argv[2] = NULL;
  440. X        if (!*list)
  441. X            set_msg_bit(msg_list, current_msg);
  442. X        move(LINES-1, 0), refresh();
  443. X        if (*list)
  444. X            iscurses = FALSE;
  445. X        /* Turn on piping to make save_msg look at msg_list */
  446. X        turnon(glob_flags, IS_PIPE);
  447. X        if (save_msg(1 + (*file != '\0'), argv, msg_list) < 0)
  448. X            *list = 0;
  449. X        turnoff(glob_flags, IS_PIPE);
  450. X        if (ison(glob_flags, CNTD_CMD))
  451. X            redo = 1, putchar('\n'), puts(compose_hdr(current_msg));
  452. X        if (*list)
  453. X            iscurses = redo = TRUE, turnon(glob_flags, CNTD_CMD);
  454. X        else if (isoff(glob_flags, CNTD_CMD) && msg_cnt) {
  455. X            move(curlin, 0);
  456. X            printw("%-.*s", COLS-1, compose_hdr(current_msg));
  457. X            }
  458. X        } else {
  459. X        print("No messages saved.");
  460. X        if (ison(glob_flags, CNTD_CMD))
  461. X            putchar('\n');
  462. X        }
  463. X    }
  464. X
  465. X    /* preserve message */
  466. X    when C_PRESERVE :
  467. X        if (!msg_cnt) {
  468. X        print("No messages.");
  469. X        if (ison(glob_flags, CNTD_CMD))
  470. X            putchar('\n');
  471. X        break;
  472. X        }
  473. X        if (ison(msg[current_msg].m_flags, PRESERVE))
  474. X        turnoff(msg[current_msg].m_flags, PRESERVE);
  475. X        else
  476. X        turnon(msg[current_msg].m_flags, PRESERVE);
  477. X        turnon(glob_flags, DO_UPDATE);
  478. X        if (ison(glob_flags, CNTD_CMD)) {
  479. X        wprint("%-.*s\n", COLS-1, compose_hdr(current_msg));
  480. X        redo = 1;
  481. X        } else {
  482. X        move(curlin, 0);
  483. X        printw("%-.*s", COLS-1, compose_hdr(current_msg));
  484. X        }
  485. X
  486. X    /* order messages (sort) and redisplay the headers */
  487. X    when C_SORT : case C_REV_SORT :
  488. X        (void) strcpy(file, "sort");
  489. X        if (c == C_REV_SORT) {
  490. X        print("Reverse "), turnon(glob_flags, CONT_PRNT);
  491. X        (void) strcat(file, " -");
  492. X        }
  493. X        print("Order messages by [Status, date, subject, author]: ");
  494. X        if ((c = m_getchar()) == 's' || c == 'S' || c == 'd' || c == 'a') {
  495. X        print("reordering messages...");
  496. X        (void) cmd_line(sprintf(buf, "%s %c", file, c), msg_list);
  497. X        print_more("done.");
  498. X        if (ison(glob_flags, CNTD_CMD))
  499. X            putchar('\n'), puts(compose_hdr(current_msg));
  500. X        redo = 1;
  501. X        } else
  502. X        clr_bot_line();
  503. X
  504. X    when C_QUIT_HARD :
  505. X        (void) quit(0, DUBL_NULL);
  506. X        redo = 1; /* new mail must have come in */
  507. X
  508. X    /* quit or update -- vrfy_update (returns 1 if updated) */
  509. X    when C_QUIT : case C_UPDATE : {
  510. X        u_long do_update = ison(glob_flags, DO_UPDATE);
  511. X        clr_bot_line();
  512. X        if (!vrfy_update(&redo))
  513. X        if (c == C_UPDATE)
  514. X            break;
  515. X        else
  516. X            turnoff(glob_flags, DO_UPDATE);
  517. X        if (c == C_QUIT) {
  518. X        if (do_update)
  519. X            putchar('\n');
  520. X        cleanup(0);
  521. X        redo = 1;
  522. X        } else if (isoff(glob_flags, CNTD_CMD))
  523. X        (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1),
  524. X                msg_list);
  525. X    }
  526. X
  527. X    when C_EXIT : case C_EXIT_HARD :
  528. X        clr_bot_line();
  529. X        iscurses = FALSE;
  530. X        if (c != C_EXIT && c != C_EXIT_HARD)
  531. X        putchar('\n');
  532. X        cleanup(0);
  533. X
  534. X    /* change to a new folder */
  535. X    when C_FOLDER :
  536. X        for (;;) {
  537. X        SIGRET (*oldint)(), (*oldquit)();
  538. X        on_intr();
  539. X        print("New folder (?=list): ");
  540. X        c = Getstr(file, COLS-22, 0);
  541. X        off_intr();
  542. X        if (c > 0) {
  543. X            if (!strcmp(file, "?")) {
  544. X            clr_bot_line();
  545. X            iscurses = 0;
  546. X            puts("folders in your folder directory:");
  547. X            (void) cmd_line(strcpy(buf, "\\folders"), msg_list);
  548. X    puts("Precede folder names with a +. `%' to specify system mailbox.");
  549. X            turnon(glob_flags, CNTD_CMD), iscurses = 1;
  550. X            continue;
  551. X            }
  552. X            clearok(stdscr, FALSE);
  553. X            /* if vrfy_update doesn't verify, but folder command fails,
  554. X             * then we need to reset the updatability of current folder
  555. X             */
  556. X            c = (ison(glob_flags, DO_UPDATE))? TRUE : FALSE;
  557. X            if (strcmp(file, "-?"))
  558. X            (void) vrfy_update(&redo);
  559. X            move(LINES-1, 0), refresh();
  560. X            if (cmd_line(sprintf(buf, "folder ! -N %s", file),
  561. X                 msg_list) == -1) {
  562. X            if (c) /* remember state of updatability of folder */
  563. X                turnon(glob_flags, DO_UPDATE);
  564. X            if (ison(glob_flags, CNTD_CMD))
  565. X                putchar('\n');
  566. X            } else
  567. X            redo = 1, turnoff(glob_flags, CNTD_CMD);
  568. X            break;
  569. X        } else {
  570. X            print("\"%s\" unchanged.", mailfile);
  571. X            if (ison(glob_flags, CNTD_CMD))
  572. X            putchar('\n');
  573. X            break;
  574. X        }
  575. X        }
  576. X
  577. X    /* shell escape */
  578. X    when C_SHELL_ESC :
  579. X        print("Shell command: ");
  580. X        if (Getstr(file, COLS-24, 0) < 0)
  581. X        clr_bot_line();
  582. X        else {
  583. X        putchar('\n');
  584. X        iscurses = FALSE;
  585. X        (void) cmd_line(sprintf(buf, "sh %s", file), msg_list);
  586. X        iscurses = TRUE;
  587. X        turnon(glob_flags, CNTD_CMD);
  588. X        }
  589. X
  590. X    /* do a line-mode like command */
  591. X    when C_CURSES_ESC :
  592. X        print(":");
  593. X        if (Getstr(buf, COLS-2, 0) < 0)
  594. X        break;
  595. X        putchar('\n');
  596. X        iscurses = FALSE;
  597. X        if (!*buf) {
  598. X        /* return -1 because iscurses = 0 is not enough! */
  599. X        redo = 0;
  600. X        endwin(); /* this turns echoing back on! */
  601. X        echo_off();
  602. X        return -1;
  603. X        }
  604. X        (void) cmd_line(buf, msg_list);
  605. X        /* they may have affected message status or had text output */
  606. X        turnon(glob_flags, CNTD_CMD), redo = 1;
  607. X        iscurses = TRUE;
  608. X        if (msg_cnt)
  609. X        puts(compose_hdr(current_msg));
  610. X
  611. X    /* send message to printer */
  612. X    when C_PRINT_MSG : (void) lpr(0, DUBL_NULL, msg_list);
  613. X
  614. X    /* cd */
  615. X    when C_CHDIR :
  616. X        print("chdir to [~]: ");
  617. X        if (Getstr(file, COLS-12, 0) < 0)
  618. X        break;
  619. X        clr_bot_line();
  620. X        (void) cmd_line(sprintf(buf, "cd %s", file), msg_list);
  621. X        if (ison(glob_flags, CNTD_CMD))
  622. X        putchar('\n');
  623. X
  624. X    /* variable settings */
  625. X    when C_VAR_SET : case C_IGNORE : case C_ALIAS : case C_OWN_HDR :
  626. X        curs_vars(c); /* CNTD_CMD is reset if there's output! */
  627. X
  628. X    when C_VERSION :
  629. X        (void) do_version();
  630. X        if (ison(glob_flags, CNTD_CMD))
  631. X        putchar('\n');
  632. X
  633. X    when C_MAIL_FLAGS :
  634. X        print("flags [-?]: ");
  635. X        if ((c = Getstr(file, COLS-12, 0)) < 0)
  636. X        break;
  637. X        putchar('\n');
  638. X        if (c == 0)
  639. X        (void) strcpy(file, "-?");
  640. X    /* Fall thru */
  641. X    case C_MAIL : {
  642. X        u_long flgs = glob_flags;
  643. X        turnon(glob_flags, IGN_BANG);
  644. X        clr_bot_line();
  645. X        iscurses = FALSE;
  646. X        (void) cmd_line(sprintf(buf, "mail %s", file), msg_list);
  647. X        glob_flags = flgs;
  648. X        iscurses = TRUE, turnon(glob_flags, CNTD_CMD);
  649. X        if (msg_cnt)
  650. X        print("%-.*s", COLS-2, compose_hdr(current_msg)), putchar('\n');
  651. X    }
  652. X
  653. X    /* reply to mail */
  654. X    when C_REPLY_SENDER : case C_REPLY_ALL : {
  655. X        register char *p = (c == C_REPLY_ALL)? "replyall" : "replysender";
  656. X        clr_bot_line();
  657. X        iscurses = FALSE;
  658. X        if (isoff(msg[current_msg].m_flags, REPLIED))
  659. X        redo = 1;
  660. X        (void) cmd_line(sprintf(buf, "%s %d", p, current_msg+1),
  661. X        msg_list);
  662. X        if (msg_cnt)
  663. X        puts(compose_hdr(current_msg));
  664. X        iscurses = TRUE, turnon(glob_flags, CNTD_CMD);
  665. X    }
  666. X
  667. X    /* type out a message */
  668. X    when C_DISPLAY_MSG : case C_TOP_MSG : case C_DISPLAY_NEXT :
  669. X        if (!msg_cnt ||
  670. X        c != C_DISPLAY_NEXT && ison(msg[current_msg].m_flags, DELETE)) {
  671. X        if (!msg_cnt)
  672. X            print("No messages.");
  673. X        else
  674. X            print("Message %d deleted; type 'u' to undelete.",
  675. X                      current_msg+1);
  676. X        if (ison(glob_flags, CNTD_CMD))
  677. X            putchar('\n');
  678. X        break;
  679. X        }
  680. X        clr_bot_line();
  681. X        iscurses = FALSE;
  682. X        if (ison(glob_flags, CNTD_CMD))
  683. X        putchar('\n');
  684. X        if (c == C_DISPLAY_MSG)
  685. X        c = cmd_line(strcpy(buf, "type"), msg_list);
  686. X        else if (c == C_TOP_MSG)
  687. X        c = cmd_line(strcpy(buf, "top"), msg_list);
  688. X        else
  689. X        c = cmd_line(strcpy(buf, "next"), msg_list);
  690. X        if (c > -1)
  691. X        turnon(glob_flags, CNTD_CMD), redo = 1;
  692. X        iscurses = TRUE;
  693. X        puts(compose_hdr(current_msg));
  694. X
  695. X    /* bind a key or string to a curses-mode command */
  696. X    when C_BIND :  case C_UNBIND : case C_MAP : case C_BIND_MACRO :
  697. X    case C_MAP_BANG : {
  698. X        char *argv[2];
  699. X        argv[0] = (c == C_BIND) ? "bind" :
  700. X              (c == C_UNBIND) ? "unbind" :
  701. X              (c == C_MAP) ? "map" :
  702. X              (c == C_MAP_BANG) ? "map!" : "bind-macro";
  703. X        argv[1] = NULL;
  704. X        if (bind_it(1, argv) < -1)
  705. X        turnon(glob_flags, CNTD_CMD);
  706. X        else if (ison(glob_flags, CNTD_CMD)) /* if it was set anyway */
  707. X        putchar('\n');
  708. X        else
  709. X        curses_help_msg(TRUE);
  710. X    }
  711. X
  712. X    when C_MACRO : 
  713. X        turnon(glob_flags, IN_MACRO);
  714. X        /* Current macro should already be in the mac_stack, so
  715. X         * all we have to do here is look for the next character
  716. X         */
  717. X
  718. X    /* help stuff */
  719. X    when C_HELP :
  720. X        move(LINES-1, 0), refresh();
  721. X        help(0, "curses", cmd_help);
  722. X        turnon(glob_flags, CNTD_CMD);
  723. X        if (msg_cnt)
  724. X        puts(compose_hdr(current_msg));
  725. X
  726. X    otherwise :
  727. X        mac_flush();
  728. X        bell();
  729. X        if (ison(glob_flags, CNTD_CMD)) {
  730. X        /* use print instead of puts to overwrite hit_return msg */
  731. X        print("unknown command"), putchar('\n');
  732. X        redo = 1;
  733. X        }
  734. X    }
  735. X
  736. X    if (ison(glob_flags, CNTD_CMD)) {
  737. X    int old_cnt = msg_cnt;
  738. X    if (!(c = hit_return()) && !redo && msg_cnt == old_cnt)
  739. X        redraw();
  740. X    clr_bot_line();
  741. X    if (old_cnt !=  msg_cnt)
  742. X        redo = 1;
  743. X    if (c)
  744. X        return c;
  745. X    }
  746. X    if (redo) {
  747. X    set_screen_size(); /* it may have changed */
  748. X    n = current_msg;
  749. X    clear();
  750. X    if (msg_cnt < screen || n_array[0] < n && n < n_array[screen-1])
  751. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  752. X    else
  753. X        (void) cmd_line(sprintf(buf, "\\headers %d", n+1), msg_list);
  754. X    (void) curses_help_msg(TRUE);
  755. X    redo = 0;
  756. X    }
  757. X    return 0;
  758. X}
  759. X
  760. Xvrfy_update(redo)
  761. Xint *redo;
  762. X{
  763. X    char buf[16];
  764. X    int c;
  765. X
  766. X    /* update current folder */
  767. X    if (ison(glob_flags, DO_UPDATE)) {
  768. X    if (ison(glob_flags, READ_ONLY)) {
  769. X        mac_flush();
  770. X        print("Folder is read-only.");
  771. X        if (ison(glob_flags, CNTD_CMD))
  772. X        putchar('\n');
  773. X        return 0;
  774. X    }
  775. X    print("Update folder [y]? ");
  776. X    if ((c = getchar()) != 'y' && c != 'Y' && c != '\n' && !isspace(c)) {
  777. X        print("Folder unchanged.");
  778. X        if (ison(glob_flags, CNTD_CMD))
  779. X        putchar('\n');
  780. X        return 0;
  781. X    }
  782. X    if (cmd_line(strcpy(buf, "update"), msg_list) != -1 &&
  783. X        ison(glob_flags, CNTD_CMD))
  784. X        *redo = 1, turnoff(glob_flags, CNTD_CMD);
  785. X    }
  786. X    turnoff(glob_flags, DO_UPDATE);
  787. X    return 1; /* make sure bottom line is clear and no reverse video */
  788. X}
  789. X
  790. Xscrn_line(line, buf)
  791. Xchar *buf;
  792. X{
  793. X#ifndef A_CHARTEXT
  794. X    (void) strncpy(buf, stdscr->_y[line], COLS-1);
  795. X    buf[COLS-1] = 0; /* strncpy does not null terminate */
  796. X#else
  797. X    int n;
  798. X
  799. X    for (n = 0; n < COLS; n++)
  800. X    if ((buf[n] = (mvinch(line, n) & A_CHARTEXT)) == '\0')
  801. X        break;
  802. X    buf[n] = '\0';
  803. X#endif /* A_CHARTEXT */
  804. X}
  805. X
  806. X/*
  807. X * Generate the help message from the variable curses_help.
  808. X *  If visible is true, the message is displayed,
  809. X *  otherwise its size (in lines) is computed and returned.
  810. X */
  811. Xcurses_help_msg(visible)
  812. Xint visible;
  813. X{
  814. X    int count, i, len, siz = 0, mxm = 0;
  815. X    static int old_siz = 0;
  816. X    register struct cmd_map *list;
  817. X    extern struct cmd_map map_func_names[];
  818. X    char *curs_help = do_set(set_options, "curses_help"), **format;
  819. X
  820. X    if (!curs_help) {
  821. X    if (old_siz && visible) {
  822. X        int bot = min(n_array[screen-1], msg_cnt-1);
  823. X        move(max(0, bot - n_array[0]) + 2, 0), clrtobot();
  824. X        old_siz = 0;
  825. X    }
  826. X    return 0;
  827. X    } else if (!*curs_help)
  828. X    curs_help = DEF_CURSES_HELP;
  829. X    /* Split the help string into words */
  830. X    if (!(format = mk_argv(curs_help, &count, FALSE)) || count <= 0)
  831. X    return 0;
  832. X    /* Generate a help message for each word */
  833. X    for (i = 0; i < count; i++) {
  834. X    char buf[MAX_BIND_LEN*2+MAX_LONG_CMD+5], asc[MAX_BIND_LEN*2];
  835. X
  836. X    buf[0] = '\0'; /* default to empty in case of no match */
  837. X    for (list = cmd_map; list; list = list->m_next) {
  838. X        if (!strcmp(format[i], map_func_names[list->m_cmd].m_str)) {
  839. X        len = strlen(sprintf(buf, "(%s) %s  ",
  840. X                ctrl_strcpy(asc, list->m_str, FALSE),
  841. X                map_func_names[list->m_cmd].m_str));
  842. X        if (len > mxm)
  843. X            mxm = len;
  844. X        break;
  845. X        }
  846. X    }
  847. X    strdup(format[i], buf); /* replace word with its "definition" */
  848. X    }
  849. X    /* Columnate the output nicely */
  850. X    if (mxm > 0) {
  851. X    len = (COLS - 1) / mxm;
  852. X    if (len == 0) {
  853. X        if (visible)
  854. X        print("Curses help message too long!");
  855. X        return 0;
  856. X    }
  857. X    siz = count / len;
  858. X    if (count % len)
  859. X        siz++;
  860. X    if (siz > LINES / 3) {
  861. X        if (visible)
  862. X        print("Curses help message too long!");
  863. X        return 0;
  864. X    }
  865. X    if (visible) {
  866. X        int next = LINES - 1 - siz;
  867. X        if (old_siz > siz) {
  868. X        int bot = min(n_array[screen-1], msg_cnt-1);
  869. X        move(max(0, bot - n_array[0]) + 2, 0), clrtobot();
  870. X        }
  871. X        old_siz = siz;
  872. X        for (i = 0; i < count; i++) {
  873. X        if (!(i % len))
  874. X            move(next, 0), clrtoeol(), ++next;
  875. X        if (format[i][0])
  876. X            printw("%-*.*s", mxm, mxm, format[i]);
  877. X        }
  878. X        refresh();
  879. X    }
  880. X    }
  881. X    free_vec(format);
  882. X    return siz;
  883. X}
  884. X
  885. Xset_screen_size()
  886. X{
  887. X    int hlp_siz = LINES - 2 - curses_help_msg(FALSE); 
  888. X
  889. X    if (!do_set(set_options, "screen"))
  890. X#ifdef USG
  891. X    switch (_tty.sg_ospeed & CBAUD)
  892. X#else /* USG */
  893. X    switch (_tty.sg_ospeed)
  894. X#endif /* USG */
  895. X    {
  896. X        case B300 :  screen = min(hlp_siz, 7);
  897. X        when B1200 : screen = min(hlp_siz, 14);
  898. X        when B2400 : screen = min(hlp_siz, 22);
  899. X        otherwise :  screen = hlp_siz;
  900. X    }
  901. X    else
  902. X    screen = min(screen, hlp_siz);
  903. X}
  904. X
  905. X/*
  906. X * prompt for a carriage return, but return whatever user types unless
  907. X * it's a character which he might regret (like 'q' or 'x'). Ignore
  908. X * interrupts (kind of) because we have nowhere to longjmp to.  When we
  909. X * return, we'll setjmp again (top of loop.c)
  910. X */
  911. Xhit_return()
  912. X{
  913. X    int c;
  914. X
  915. X    turnon(glob_flags, IGN_SIGS);
  916. X    iscurses = FALSE;
  917. X    (void) check_new_mail();
  918. X    iscurses = TRUE;
  919. X    mail_status(1), addstr("...continue... "), refresh();
  920. X    c = getcmd();
  921. X    turnoff(glob_flags, IGN_SIGS);
  922. X
  923. X    /* don't let the user type something he might regret */
  924. X    if (c == C_QUIT || c == C_EXIT)
  925. X    return C_NULL;
  926. X    return c;
  927. X}
  928. X
  929. Xcurses_msg_list(str, list, m_list)
  930. Xregister char *str, *list;
  931. Xchar m_list[];
  932. X{
  933. X    register char *p = NULL;
  934. X    int c, sv_cur_msg = current_msg;
  935. X
  936. X    print(str);
  937. X    c = Getstr(list, COLS-13, 0);
  938. X    move(LINES-1, 0), refresh();
  939. X    if (c <= 0 || !(p = do_range(list, m_list)) ||
  940. X    (p == list && *p && *p != '$' && *p != '^')) {
  941. X    if (p)
  942. X        print("Invalid message list: %s", p);
  943. X    current_msg = sv_cur_msg;
  944. X    return 0;
  945. X    }
  946. X    current_msg = sv_cur_msg;
  947. X    return 1;
  948. X}
  949. X
  950. Xcurs_vars(which)
  951. Xint which;  /* really, a char */
  952. X{
  953. X    char c, buf[128], buf2[128], *string;
  954. X    struct options **list;
  955. X
  956. X    switch(which) {
  957. X    case C_OWN_HDR : string = "my_hdr", list = &own_hdrs;
  958. X    when C_ALIAS : string = "alias", list = &aliases;
  959. X    when C_IGNORE : string = "ignore", list = &ignore_hdr;
  960. X    when C_VAR_SET : string = "set", list = &set_options;
  961. X    otherwise : clr_bot_line(); return;
  962. X    }
  963. X
  964. X    print("%s [? Set Unset All]: ", string);
  965. X    c = m_getchar();
  966. X    clr_bot_line();
  967. X    switch (Lower(c)) {
  968. X    /* if help, print help -- if "all", show all settings. */
  969. X    case '?' : case 'a' :
  970. X        if (c == '?') {
  971. X        if (!strcmp(string, "set")) {
  972. X            print("which variable? [all <var>]: ");
  973. X            if ((c = Getstr(buf+1, COLS-40, 0)) < 0)
  974. X            return;
  975. X            clr_bot_line();
  976. X            buf[0] = '?';
  977. X            if (c > 0) {
  978. X            char *argv[3];
  979. X            argv[0] = string;
  980. X            argv[1] = buf;
  981. X            argv[2] = NULL;
  982. X            Lower(buf[1]);
  983. X            if (!strcmp(buf+1, "a"))
  984. X                (void) strcpy(buf+1, "all");
  985. X            if (!strcmp(buf+1, "all"))
  986. X                turnon(glob_flags, CNTD_CMD);
  987. X            (void) set(2, argv);
  988. X            break;
  989. X            }
  990. X        }
  991. X        /* help returns next command (hit_return) */
  992. X        help(0, string, cmd_help);
  993. X        turnon(glob_flags, CNTD_CMD);
  994. X        return;
  995. X        }
  996. X        turnon(glob_flags, CNTD_CMD);
  997. X        (void) do_set(*list, NULL);
  998. X
  999. X    /* if set, prompt for string and let user type */
  1000. X    when 's' :
  1001. X        print("set: ");
  1002. X        c = Getstr(buf, COLS-18, 0);
  1003. X        clr_bot_line();
  1004. X        if (c > 0)
  1005. X        (void) cmd_line(sprintf(buf2, "%s %s", string, buf), msg_list);
  1006. X
  1007. X    /* if unset, just as easy as set! */
  1008. X    when 'u' :
  1009. X        print("unset: ", string);
  1010. X        if (Getstr(buf, COLS-18, 0) > 0 && !un_set(list, buf))
  1011. X        print("%s isn't set", buf);
  1012. X    }
  1013. X    if (ison(glob_flags, CNTD_CMD))
  1014. X    putchar('\n');
  1015. X    else
  1016. X    curses_help_msg(TRUE);
  1017. X}
  1018. X#endif /* CURSES */
  1019. END_OF_FILE
  1020. if test 27579 -ne `wc -c <'curses.c'`; then
  1021.     echo shar: \"'curses.c'\" unpacked with wrong size!
  1022. fi
  1023. # end of 'curses.c'
  1024. fi
  1025. echo shar: End of archive 12 \(of 19\).
  1026. cp /dev/null ark12isdone
  1027. MISSING=""
  1028. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1029.     if test ! -f ark${I}isdone ; then
  1030.     MISSING="${MISSING} ${I}"
  1031.     fi
  1032. done
  1033. if test "${MISSING}" = "" ; then
  1034.     echo You have unpacked all 19 archives.
  1035.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1036. else
  1037.     echo You still need to unpack the following archives:
  1038.     echo "        " ${MISSING}
  1039. fi
  1040. ##  End of shell archive.
  1041. exit 0
  1042.